package com.jch.dm3_two_phase_termination.extension;

import java.util.Random;
import java.util.concurrent.*;

public class TestCyclicBarrierMain {

    private static final int THREADS = 3;

    public static void main(String[] args) {
        System.out.println("BEGIN");
        // 提供进行工作的线程
        ExecutorService service = Executors.newFixedThreadPool(THREADS);
        // 解除屏障操作
        Runnable barrierAction = new Runnable() {
            @Override
            public void run() {
                System.out.println("Barrier Action!");
            }
        };
        // 使线程步调一致
        CyclicBarrier phaseBarrier = new CyclicBarrier(THREADS,barrierAction);
        // 用于确认工作是否结束
        CountDownLatch doneLatch = new CountDownLatch(THREADS);
        try{
            for (int t = 0; t < THREADS; t++){
                service.execute(new MyTask1(phaseBarrier,doneLatch,t));
            }
            // 等待工作结束
            System.out.println("AWAIT");
            doneLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            service.shutdown();
            System.out.println("END");
        }
    }

}

class MyTask1 implements Runnable{

    private static final int PHASE = 5;
    private final CyclicBarrier phaseBarrier;
    private final CountDownLatch doneLatch;
    private final int context;
    private static final Random random = new Random(314159);

    public MyTask1(CyclicBarrier phaseBarrier, CountDownLatch doneLatch, int context) {
        this.phaseBarrier = phaseBarrier;
        this.doneLatch = doneLatch;
        this.context = context;
    }

    @Override
    public void run() {
        try{
            for (int phase = 0; phase < PHASE; phase++){
                doPhase(phase);
                phaseBarrier.await();
            }
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        } finally {
            doneLatch.countDown();
        }
    }

    protected void doPhase(int phase){
        String name = Thread.currentThread().getName();
        System.out.println(name + ":MyTask:BEGIN:context: = " + context + ", phase = " + phase);
        try{
            Thread.sleep(random.nextInt(3000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            System.out.println(name + ":MyTask:END:context = " + context + ", phase = " + phase);
        }
    }
}